﻿/*
 * Created by SharpDevelop.
 * User: Chad Weimer
 * Date: 10/21/2011
 * Time: 9:04 AM
 * 
 * To change this template use Tools | Options | Coding | Edit Standard Headers.
 */
using System;
using System.Collections.Generic;
using System.ComponentModel.Composition;
using System.Diagnostics;
using System.Linq;

using DotNetOpenAuth.OAuth2;
using Google.Apis.Authentication;
using Google.Apis.Authentication.OAuth2;
using Google.Apis.Authentication.OAuth2.DotNetOpenAuth;
using Google.Apis.Samples.Helper;
using Google.Apis.Tasks.v1;
using Google.Apis.Util;
using Tasx.Definitions;
using GTaskLists = Google.Apis.Tasks.v1.Data.TaskLists;
using GTaskList = Google.Apis.Tasks.v1.Data.TaskList;
using GTasks = Google.Apis.Tasks.v1.Data.Tasks;
using GTask = Google.Apis.Tasks.v1.Data.Task;

namespace Tasx.Providers.GoogleTasks
{
	[Export(typeof(ITaskProvider))]
	[ExportMetadata("Name", "Google")]
	public class GoogleTaskProvider : ITaskProvider
	{
		private TasksService _taskService;
		
		public GoogleTaskProvider()
		{
			_taskService = new TasksService(GetAuthenticator());
		}
		
		public string Name
		{
			get { return "Google"; }
		}

        public TasksProxy Sync(TasksProxy proxy)
        {
            // Sync the current data
            if (proxy != null)
            {
                
            }

            // Get the latest data
            var lists = GetLists();
            var tasks = GetTasks(lists);

            return new TasksProxy {Lists = lists, Tasks = tasks};
        }

        private IList<TaskList2> GetLists()
        {
            GTaskLists gTaskLists = _taskService.Tasklists.List().Fetch();
            return gTaskLists.Items.Select(list => new TaskList2 {Name = list.Title, Context = list}).ToList();
        }

        private IList<Task2> GetTasks(IEnumerable<TaskList2> lists)
        {
            var tasks = new List<Task2>();
            foreach (var list in lists)
            {
                var gTasks = _taskService.Tasks.List(((GTaskList)list.Context).Id).Fetch();
                if (gTasks.Items == null)
                {
                    continue;
                }

                tasks.AddRange(
                    gTasks.Items.Select(task => new Task2
                                                {
                                                    Summary = task.Title,
                                                    Notes = task.Notes,
                                                    Completed = !string.IsNullOrEmpty(task.Completed)
                                                }));
            }

            return tasks;
        }
		
		private IAuthenticator GetAuthenticator()
		{
			var provider = new NativeApplicationClient(GoogleAuthenticationServer.Description);
			provider.ClientIdentifier = ClientCredentials.ClientID;
			provider.ClientSecret = ClientCredentials.ClientSecret;
			return new OAuth2Authenticator<NativeApplicationClient>(provider, GetAuthorization);
		}

		private static IAuthorizationState GetAuthorization(NativeApplicationClient client)
		{
			// You should use a more secure way of storing the key here as
			// .NET applications can be disassembled using a reflection tool.
			const string STORAGE = "google.samples.dotnet.tasks";
			const string KEY = "y},drdzf11x9;87";
			string scope = TasksService.Scopes.Tasks.GetStringValue();

			// Check if there is a cached refresh token available.
			IAuthorizationState state = AuthorizationMgr.GetCachedRefreshToken(STORAGE, KEY);
			if (state != null)
			{
				try
				{
					client.RefreshToken(state);
					return state; // Yes - we are done.
				}
				catch (DotNetOpenAuth.Messaging.ProtocolException ex)
				{
					CommandLine.WriteError("Using existing refresh token failed: " + ex.Message);
				}
			}

			// Retrieve the authorization from the user.
			state = AuthorizationMgr.RequestNativeAuthorization(client, scope);
			AuthorizationMgr.SetCachedRefreshToken(STORAGE, KEY, state);
			return state;
		}
	}
}